﻿using IBatisNet.DataMapper;
using IBatisNet.DataMapper.Configuration;
using System.Collections.Generic;
using IBatisNet.DataMapper.Configuration.Statements;
using System.Data;
using IBatisNet.DataMapper.Scope;
using IBatisNet.DataMapper.MappedStatements;

namespace Lyh.MyBatis.DAL
{
    /// <summary>
    /// Author：lyh
    /// Description：SqlMapper Singleton
    /// Date：2013-11-03
    /// </summary>
    public class Mapper
    {
        private static readonly ISqlMapper instance;
        /// <summary>
        /// SqlMapper 实例
        /// </summary>
        public static ISqlMapper Instance
        {
            get
            {
                return instance;
            }
        }

        private Mapper()
        {
        }

        static Mapper()
        {
            var builder = new DomSqlMapBuilder();
            instance = builder.Configure();
        }



        /// <summary>
        /// lyh：获得IBatisNet实际执行的SQL语句
        /// </summary>
        /// <param name="statementName"></param>
        /// <param name="paramObject"></param>
        /// <returns></returns>
        public static string GetSql(string statementName, object paramObject)
        {
            IMappedStatement mappedStatement = Instance.GetMappedStatement(statementName);
            IStatement statement = mappedStatement.Statement;
            RequestScope request = statement.Sql.GetRequestScope(mappedStatement, paramObject, new SqlMapSession(Instance));
            return request.PreparedStatement.PreparedSql;
        }

        /// <summary>
        /// lyh:返回DataSet类型数据
        /// </summary>
        /// <param name="statementName">SQL段名</param>
        /// <param name="paramObject">参数</param>
        /// <returns>DataSet</returns>
        public static DataSet QueryForDataSet(string statementName, object paramObject)
        {
            DataSet ds = new DataSet();
            IDbCommand cmd = GetDbCommand(statementName, paramObject);
            Instance.LocalSession.CreateDataAdapter(cmd).Fill(ds);
            return ds;
        }

        /// <summary>
        /// lyh：获得 DbCommand 对象
        /// </summary>
        /// <param name="statementName"></param>
        /// <param name="paramObject"></param>
        /// <returns></returns>
        public static IDbCommand GetDbCommand(string statementName, object paramObject)
        {
            IStatement statement = Instance.GetMappedStatement(statementName).Statement;
            IMappedStatement mappedStatement = Instance.GetMappedStatement(statementName);
            ISqlMapSession session = new SqlMapSession(Instance);

            if (Instance.LocalSession != null)
            {
                session = Instance.LocalSession;
            }
            else
            {
                session = Instance.OpenConnection();
            }

            RequestScope request = statement.Sql.GetRequestScope(mappedStatement, paramObject, session);
            mappedStatement.PreparedCommand.Create(request, session, statement, paramObject);

            IDbCommand cmd = session.CreateCommand(CommandType.Text);
            cmd.CommandText = request.IDbCommand.CommandText;

            AddParameters(paramObject, statement, cmd);

            return cmd;
        }

        /// <summary>
        /// lyh：添加参数
        /// </summary>
        /// <param name="paramObject">IDictionary<string, object></param>
        /// <param name="statement"></param>
        /// <param name="cmd"></param>
        private static void AddParameters(object paramObject, IStatement statement, IDbCommand cmd)
        {
            if (statement.ParameterMap == null) return;
            if (paramObject is IDictionary<string, object>)
            {
                var args = paramObject as IDictionary<string, object>;
                for (var i = 0; i < statement.ParameterMap.PropertiesList.Count; i++)
                {
                    var property = statement.ParameterMap.GetProperty(i);
                    var dbParam = cmd.CreateParameter();
                    dbParam.ParameterName = string.Format("param{0}", i);
                    dbParam.Value = args[property.PropertyName];
                    cmd.Parameters.Add(dbParam);
                }
            }
        }
    }
}